<html>

<head>
  <script src="https://unpkg.com/@tensorflow/tfjs"></script>
</head>
<script>
  // 主题：Y 等于 2X 减去 1

  // 将模型定义为连续模型
  const model = tf.sequential();
  // 创建最简单的神经网络，一层只有一个单元，在序列中添加一个密集层
  model.add(tf.layers.dense({ units: 1, inputShape: [1] }));
  // 编译一个带有损失函数和优化器的神经网络
  // 损失函数是 Mean Squared Error， 它 在这样的线性关系中效果非常好
  // 优化器中的 SGD 代表 随机梯度下降
  model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' })
  // 输出模型定义
  model.summary();
  // 用来训练神经网络的数据（ 2D 张量）
  // 当使用 Tensor 2D 时， 你有一个二维数组 或两个一维数组。
  // 训练值在第一个数组中 ，第二个数组是 这些训练值的形状
  const xs = tf.tensor2d([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], [6, 1])
  const ys = tf.tensor2d([-3.0, -1.0, 2.0, 3.0, 5.0, 7.0], [6, 1])

  // 训练模型
  // 训练应该是一个异步函数 ，因为它需要不确定的时间才能完成。
  // 把你刚才创建的模型传递给它。
  doTraining(model).then(() => {
    // 当它完成后会回调我们
    // 我们可以用它 来尝试预测 10 的值
    // 我们必须再次创建一个 Tensor 2D， 
    // 其中第一个维度是一个 包含我们要预测的值的数组， 
    // 在本例中为 10， 第二个维度是 该数组的大小，在本例中是一个
    alert(model.predict(tf.tensor2d([10], [1, 1])))
  })


  // 训练模型的函数
  async function doTraining() {
    // model.fit 开始训练
    const history = await model.fit(xs, ys, {
      // 迭代次数
      'epochs': 500,
      // 函数回调
      'callbacks': {
        // 当一次迭代结束后
        onEpochEnd: async (epoch, logs) => {
          console.log("Epoch:" + epoch + ' Loss:' + logs.loss);
        }
      }
    })
  }
</script>

</html>